package org.fhnw.aigs.server.gui; import java.awt.Dimension; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.GroupLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.LayoutStyle; import javax.swing.UIManager; import javax.swing.WindowConstants; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import org.fhnw.aigs.server.gameHandling.User; /** * This class represents a window to manage the user settings. These settings * will be stored in {@link User#users}. The user management is only applying * if anonymous login is disable (users have to log in).<br> * v1.0 Initial release<br> * v1.1 Changing look&feel to 'Nimbus' (Platform independent) * @author Raphael Stoeckli (29.10.2014) * @version 1.1 (Raphael Stoeckli (13.04.2015) */ public class UserSettingsWindow extends JDialog { private JButton addButton; private JButton alterButton; private JButton cancelButton; private JButton newButton; private JButton removeButton; private JButton saveButton; private JLabel userIDLabel; private JList userList; private JTextField usernameField; private JTextField passwordField; private Vector<User> userContent; private User currentUser; private boolean changesApplied; /** * Standard constructor without parameters */ public UserSettingsWindow() { setLookAndFeel("Nimbus"); // Tested: "Nimbus", "Windows" ImageIcon logoImage = new ImageIcon(getClass().getResource("/imgs/logo24px.png")); this.setIconImage(logoImage.getImage()); this.setLocationByPlatform(true); // Better positioning of the window this.setResizable(false); this.setAlwaysOnTop(true); this.setModal(true); this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); this.setTitle("AIGS Server - User Management"); this.setPreferredSize(new Dimension(515, 255)); init(); loadData(); setNewUser(); } /** * Method to set a specific look and feel (Swing). If the name is not found, {@link javax.swing.UIManager#getCrossPlatformLookAndFeelClassName()} will be used.<br> * This may cause problems with the window and font sizes. * @param name Name of the look and feel theme * @since v1.1 */ private void setLookAndFeel(String name) { boolean match = false; try { for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { if (name.equals(info.getName())) { UIManager.setLookAndFeel(info.getClassName()); match = true; break; } } } catch (Exception e) { match = false; } if (match == false) { try { UIManager.setLookAndFeel(javax.swing.UIManager.getCrossPlatformLookAndFeelClassName()); } catch (Exception ex) { Logger.getLogger(SettingsWindow.class.getName()).log(Level.SEVERE, null, ex); } } } /** * Initilizes the UI. The lower part of this method was genereated by the GUI builder * of NetBeans and cleaned up by hand */ private void init() { changesApplied = false; newButton = new JButton("New"); newButton.setToolTipText("Clears all fields and prepares the form to add a new user"); addButton = new JButton("Create"); addButton.setToolTipText("Adds a new user to te user list"); alterButton = new JButton("Alter"); alterButton.setToolTipText("Alters the current selected uset"); removeButton = new JButton("Remove"); removeButton.setToolTipText("Removes the current user from the user list"); saveButton = new JButton("Save"); saveButton.setToolTipText("Saves the user settings and closes this window"); cancelButton = new JButton("Cancel"); cancelButton.setToolTipText("Discards all changes and closes this window"); userIDLabel = new JLabel(); userIDLabel.setText("---"); usernameField = new JTextField(); passwordField = new JTextField(); userContent = new Vector<User>(); userList = new JList(userContent); JLabel usernameLabel = new JLabel("User name:"); JLabel passwordLabel = new JLabel("Password:"); JLabel userIDCaptionLabel = new JLabel("User ID:"); JScrollPane usernameScrollPane = new JScrollPane(); JScrollPane passwordScrollPane = new JScrollPane(); JScrollPane userlistScrollPane = new JScrollPane(); userlistScrollPane.setViewportView(userList); usernameScrollPane.setViewportView(usernameField); passwordScrollPane.setViewportView(passwordField); newButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { newButtonActionPerformed(evt); } }); addButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { addButtonActionPerformed(evt); } }); alterButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { alterButtonActionPerformed(evt); } }); removeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { removeButtonActionPerformed(evt); } }); saveButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { saveButtonActionPerformed(evt); } }); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { cancelButtonActionPerformed(evt); } }); usernameField.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent evt) { usernameFieldKeyReleased(evt); } }); userList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { userListValueChanged(evt); } }); GroupLayout layout = new GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(passwordLabel) .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(passwordScrollPane)) .addGroup(layout.createSequentialGroup() .addComponent(usernameLabel) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(usernameScrollPane)) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addComponent(saveButton) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(cancelButton)) .addGroup(layout.createSequentialGroup() .addComponent(newButton) .addGap(6, 6, 6) .addComponent(addButton) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(alterButton) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(removeButton)) .addGroup(layout.createSequentialGroup() .addComponent(userIDCaptionLabel) .addGap(18, 18, 18) .addComponent(userIDLabel))) .addGap(0, 0, Short.MAX_VALUE))) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addComponent(userlistScrollPane, GroupLayout.DEFAULT_SIZE, 240, Short.MAX_VALUE) .addContainerGap()) ); layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(newButton) .addComponent(addButton) .addComponent(alterButton) .addComponent(removeButton)) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(userIDCaptionLabel) .addComponent(userIDLabel)) .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING) .addComponent(usernameLabel) .addComponent(usernameScrollPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING) .addComponent(passwordLabel) .addComponent(passwordScrollPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 92, Short.MAX_VALUE) .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) .addComponent(saveButton) .addComponent(cancelButton))) .addComponent(userlistScrollPane)) .addContainerGap()) ); this.addWindowListener(new UserSettingsWindow.CloseListener()); pack(); } /** * Method to load the data from {@link User#users}. */ private void loadData() { this.userContent.clear(); for(int i = 0; i < User.users.size(); i++) { if (User.users.get(i).isNonPersistentUser() == true) // No non-persistent users { continue; } this.userContent.add(User.users.get(i)); } userList.setListData(this.userContent); } /** * Metod to prepare the form for inserting a new user. This method adds no * new user to the list. Use {@link UserSettingsWindow#createNewUser()} for this task */ private void setNewUser() { userList.setSelectedIndex(-1); usernameField.setText(""); passwordField.setText(""); userIDLabel.setText("---"); removeButton.setEnabled(false); alterButton.setEnabled(false); addButton.setEnabled(false); this.currentUser = null; } /** * Method fills the data from the defined user into the form. If no user (null) * was specified {@link UserSettingsWindow#setNewUser()} will be called * @param user User to process */ private void setCurrentUser(User user) { if (user == null ) { setNewUser(); return; } usernameField.setText(user.getUserName()); passwordField.setText(user.getIdentificationCode()); userIDLabel.setText(Long.toString(user.getId())); removeButton.setEnabled(true); alterButton.setEnabled(true); addButton.setEnabled(false); this.currentUser = user; } /** * Method creates a new user into the list */ private void createNewUser() { String username = usernameField.getText(); if (username.length() == 0) { JOptionPane.showMessageDialog(this, "Please insert a valid user name", "Invalid user name", JOptionPane.INFORMATION_MESSAGE); return; } int len = this.userContent.size(); for(int i = 0; i < len; i++) { if (this.userContent.get(i).getUserName().equalsIgnoreCase(username)) { JOptionPane.showMessageDialog(this, "The user name already exists. Please select another one.", "Invalid user name", JOptionPane.INFORMATION_MESSAGE); return; } } this.currentUser = new User(username, passwordField.getText()); //setCurrentUser(this.currentUser); this.userContent.add(this.currentUser); userList.setListData(this.userContent); int size = userList.getModel().getSize(); userList.setSelectedIndex(size - 1); userList.ensureIndexIsVisible( size - 1 ); } /** * Method alters the data of the currently selected user */ private void alterUser() { if (currentUser == null) { return; } String username = usernameField.getText(); if (username.length() == 0) { JOptionPane.showMessageDialog(this, "Please insert a valid user name", "Invalid user name", JOptionPane.INFORMATION_MESSAGE); return; } int len = this.userContent.size(); for(int i = 0; i < len; i++) { if (this.userContent.get(i).getUserName().equalsIgnoreCase(username) && currentUser.getUserName().equalsIgnoreCase(username) == false) { JOptionPane.showMessageDialog(this, "The user name already exists. Please select another one.", "Invalid user name", JOptionPane.INFORMATION_MESSAGE); return; } } this.currentUser.setUserName(username); this.currentUser.setIdentificationCode(passwordField.getText()); for(int i = 0; i < this.userContent.size(); i++) { if(this.userContent.get(i).getId() == this.currentUser.getId()) { this.userContent.set(i, this.currentUser); break; } } userList.setListData(this.userContent); } /** * Method removes the currently selected user from the list */ private void deleteUser() { if (currentUser == null) { return; } int result = JOptionPane.showConfirmDialog(this, "Do you want do delete the user '" + this.currentUser.getUserName() + "'?", "Delete user", JOptionPane.YES_NO_OPTION); if (result != JOptionPane.YES_OPTION) { return; } for(int i = 0; i < this.userContent.size(); i++) { if(this.userContent.get(i).getId() == this.currentUser.getId()) { this.userContent.remove(i); break; } } this.currentUser = null; userList.setListData(this.userContent); } /** * Method stores the changes to the static user list in {@link User#users} */ private void save() { for (int i = User.users.size() -1; i >= 0; i--) { if (User.users.get(i).isNonPersistentUser() == true) { continue; } else { User.removeUserFromUserList(User.users.get(i)); // remove persistent user } } for(int i = 0; i < this.userContent.size(); i++) { User.addUserToUserList(this.userContent.get(i)); // Add persistent user } User.writeUsersToXml(); // Save persistent users } /** * Method to tigger the action of preparing a new user.<br> * see {@link UserSettingsWindow#setNewUser()} * @param evt Action event of the calling UI element */ private void newButtonActionPerformed(ActionEvent evt) { setNewUser(); } /** * Method to tigger the action of creating a new user.<br> * see {@link UserSettingsWindow#createNewUser()} * @param evt Action event of the calling UI element */ private void addButtonActionPerformed(ActionEvent evt) { createNewUser(); changesApplied = true; } /** * Method to tigger the action of altering a user.<br> * see {@link UserSettingsWindow#alterUser()} * @param evt Action event of the calling UI element */ private void alterButtonActionPerformed(ActionEvent evt) { alterUser(); changesApplied = true; } /** * Method to tigger the action of removing a user.<br> * see {@link UserSettingsWindow#deleteUser()} * @param evt Action event of the calling UI element */ private void removeButtonActionPerformed(ActionEvent evt) { deleteUser(); changesApplied = true; } /** * Method to tigger the action of saving changes.<br> * see {@link UserSettingsWindow#save()} * @param evt Action event of the calling UI element */ private void saveButtonActionPerformed(ActionEvent evt) { if (changesApplied == false) { JOptionPane.showMessageDialog(this, "No changes have been made", "No changes", JOptionPane.INFORMATION_MESSAGE); } else { save(); } CloseListener cl = new CloseListener(); cl.closeWindow(this); } /** * Method to tigger the closing action (discard changes) of the window * @param evt Action event of the calling UI element */ private void cancelButtonActionPerformed(ActionEvent evt) { CloseListener cl = new CloseListener(); cl.closeWindow(this); } /** * Method to tigger the action of changing the user selection in the list. * This is used to set the {@link UserSettingsWindow#currentUser} * @param evt Action event of the calling UI element */ private void userListValueChanged(ListSelectionEvent evt) { try { setCurrentUser((User)userList.getSelectedValue()); } catch(Exception ex) { setNewUser(); } } /** * Method to tigger the action of changing the user name. * This method is to decide whether the buttons to add, alter or remove a * user are enabled or disabled * @param evt Action event of the calling UI element */ private void usernameFieldKeyReleased(KeyEvent evt) { if (usernameField.getText().length() == 0) { alterButton.setEnabled(false); addButton.setEnabled(false); } else { if (this.currentUser == null) { alterButton.setEnabled(false); addButton.setEnabled(true); } else { alterButton.setEnabled(true); addButton.setEnabled(false); } } } /** * Class to handle the close action of the window */ private class CloseListener implements WindowListener { /** * Standard constructor */ public CloseListener() { } /** * Method to perform the actual closing action. This method can also called * by creating an instance of this class manually * @param window */ public void closeWindow(Window window) { window.dispose(); } /** This method is empty */ @Override public void windowOpened(WindowEvent e) { /* Do nothing */ } /** * Called, when closing the window * @param e Action event of the calling UI element */ @Override public void windowClosing(WindowEvent e) { this.closeWindow(e.getWindow()); } /** This method is empty */ @Override public void windowClosed(WindowEvent e) { /* Do nothing */ } /** This method is empty */ @Override public void windowIconified(WindowEvent e) { /* Do nothing */ } /** This method is empty */ @Override public void windowDeiconified(WindowEvent e) { /* Do nothing */ } /** This method is empty */ @Override public void windowActivated(WindowEvent e) { /* Do nothing */ } /** This method is empty */ @Override public void windowDeactivated(WindowEvent e) { /* Do nothing */ } } }